package client;

import gui.TableImage;
import gui.TableImage.SelectionMode;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.List;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;

import shared.PlayerPosition;
import shared.PlayerState;
import shared.RemotePlayer;

import deck.Card;
import deck.Suit;

import network.message.IMessage;
import network.message.IMessage.MessageType;
import network.message.Message;

/**
 * This class is an extension to the BasicClient class that handles Setback specific actions. 
 * @author JFIELD
 *
 */
public class SetbackClient extends BasicClient implements Runnable
{
	private RemotePlayer rPlayer;
	private TableImage tableImage;
	
	/**
	 * Host of the server to connect to.
	 */
	private String host;
	
	/**
	 * Port on the server.
	 */
	private int port;
	
	/**
	 * Boolean that is true when we are listening for messages from the server.  False, otherwise.
	 */
	private boolean listening;
	
	/**
	 * Constructor for the class.
	 * @param host
	 * @param port
	 */
	public SetbackClient(String host, int port)
	{
		this.host = host;
		this.port = port;
		tableImage = new TableImage(new Vector<Card>(), new Vector<Card>(), new Vector<Card>(), new Vector<Card>());

		JFrame frame = new JFrame();
		frame.addMouseListener(tableImage);
		frame.setMinimumSize(new Dimension(700,700));
		frame.add(tableImage);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	/**
	 * Runs the server.
	 */
	@Override
	public void run()
	{
		// Connect to the server.
		try
		{
			super.connect(host, port);
			listening = true;
		}
		catch(IOException e)
		{
			e.printStackTrace();
			// Things have gone wrong.  Return.
			listening = false;
			return;
		}
		
//		IMessage joinMessage = new Message(MessageType.SIT_MESSAGE, rPlayer);
//		send(joinMessage);
		
//		IMessage test = new Message(MessageType.SUIT_MESSAGE, Suit.CLUBS);
//		send(test);
		
		// Wait for a message.
		while(listening == true)
		{
			IMessage m = super.recieve();
			handleMessage(m);
			notifyObservers(m);
			try 
			{
				Thread.sleep(500);
			} 
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private void handleMessage(IMessage message)
	{
		switch (message.getMessageType()) {
		case BID_INFO: 
			System.out.println("Recieved a bid-info message.");
			break;
		case TRUMP_INFO: 
			System.out.println("Recieved a trump-info message.");
			break;
		case PLAYER_INFO: 
			System.out.println("Recieved a player-info message.");
			PlayerState state = (PlayerState) message.getArguements();
			tableImage.replaceHand(state.getPlayerPosition(), state.getHand());
			tableImage.setHandleForPosition(state.getPlayerPosition(), state.getName());
			break;
		case BID_MESSAGE: 
			System.out.println("Recieved a bid message");
			List<Integer> validBids = (List<Integer>) message.getArguements();
			Integer myBid = tableImage.getBid(validBids);
			IMessage bidMessage = new Message(MessageType.BID_MESSAGE, myBid);
			this.send(bidMessage);
			break;
		case SUIT_MESSAGE:
			System.out.println("Reicevd a suit message");
			Suit mySuit = tableImage.getTrump();
			IMessage suitMessage = new Message(MessageType.SUIT_MESSAGE, mySuit);
			this.send(suitMessage);
			break;
		case PLAY_MESSAGE: 
			System.out.println("Recieved a Play message");
			List<Card> playable = (List<Card>) message.getArguements();
			tableImage.setPlayableCards(rPlayer.getCurrentState().getPlayerPosition(), playable);
			tableImage.playCard(new AbstractAction() {

				@Override
				public void actionPerformed(ActionEvent e) {
					Card card = tableImage.getSelectedCard(rPlayer.getCurrentState().getPlayerPosition());
					IMessage message = new Message(MessageType.PLAY_MESSAGE, card);
					tableImage.playCard(rPlayer.getCurrentState().getPlayerPosition(), card);
					send(message);
				}
				
			});
			break;
		case TRADE_MESSAGE:
			System.out.println("Recieved a Trade message");
			List<Card> tradeable = (List<Card>) message.getArguements();
			tableImage.setPlayableCards(rPlayer.getCurrentState().getPlayerPosition(), tradeable);
			tableImage.tradeCards(new AbstractAction() {

				@Override
				public void actionPerformed(ActionEvent e) {
					List<Card> tradeIns = tableImage.getSelectedCards(rPlayer.getCurrentState().getPlayerPosition());
					IMessage message = new Message(MessageType.TRADE_MESSAGE, tradeIns);
					send(message);
				}
				
			});
			break;
		case JOIN_REQUEST:
			System.out.println("Recieved a Join message");
			PlayerPosition pos = (PlayerPosition) message.getArguements();
			rPlayer = new RemotePlayer("poop", pos);
			tableImage.replaceHand(rPlayer.getCurrentState().getPlayerPosition(), rPlayer.getCurrentState().getHand());
			IMessage joinMessage = new Message(MessageType.SIT_MESSAGE, rPlayer);
			send(joinMessage);
			break;
		case DEAL_MESSAGE:
			System.out.println("Recieved a Deal message");
			break;
		case ROUND_INFO:
			System.out.println("Recieved a Round Info message");
		}
	}
	
	public static void main(String[] args)
	{
		String host = "localhost";//args[0];
		int port = 5555; //Integer.parseInt(args[1]);
		
		SetbackClient client = new SetbackClient(host, port);
		new Thread(client).start();
		
		

	}
}
